const { isMainThread, parentPort, workerData } = require('worker_threads')
const mysql = require('mysql2/promise');
const dbhealper = require('../utils/dbhealper');
const axiosUitl = require("../utils/axios");
const proxyCenter = require("./proxy");
const { sleep } = require('../utils/utils');

if (isMainThread) {
    return
}

const runWorker = async () => {
    setTimeout(() => {
        runWorker()
    }, 30 * 60 * 1000 + 1000);
    const conn = await mysql.createConnection(dbhealper.config)

    await conn.query("update hamsterkombat set sync=0 where id>0")
    // 一次10个并行
    let index = 0
    const proxyList = proxyCenter.proxyList
    while (true) {
        await sleep(2000)
        try {
            const step = 30
            let [results, fields] = await conn.query("select * from hamsterkombat where sync=0 limit ?", [step])
            if (results.length == 0 || results == null) {
                break
            }
            let promises = []
            for (let i = 0; i < results.length; i++) {
                const proxyIndex = index % proxyList.length
                const proxy = proxyList[proxyIndex]
                const element = results[i]
                if (element.token == null || element.token.length == 0) {
                    continue
                }
                const unit = new HamsterkombatUnit(element, proxy, conn)
                const prms = unit.run()
                promises.push(prms)
                index++
            }
            await Promise.allSettled(promises)
            console.log(Date(), "finished " + index + "..<" + (index + results.length))
        } catch (error) {
            console.error(Date(), error.message)
            continue
        }
    }
    await conn.end();
}

class HamsterkombatUnit {
    constructor(tokenInfo, proxyInfo, sqlconn) {
        this.tokenInfo = tokenInfo
        this.proxyInfo = proxyInfo
        this.sqlconn = sqlconn
    }

    getProxy() {
        if (this.proxyInfo == null) {
            return null
        }
        return {
            protocol: "http",
            host: this.proxyInfo.ip,
            port: this.proxyInfo.port,
        }
    }

    async run() {
        try {
            const proxy = axiosUitl.parseProxy(this.proxyInfo)
            const axios = axiosUitl.createAxios(proxy)
            const headers = {
                'Authorization': this.tokenInfo.token
            }
            const authResp = await axios.request("https://api.hamsterkombat.io/auth/me-telegram", {
                method: "post",
                headers,
            })

            // tasks
            // 一次完成一个任务
            const listTasksResp = await axios.request("https://api.hamsterkombat.io/clicker/list-tasks", {
                method: "post",
                headers,
            })
            const listTasks = listTasksResp.data.tasks
            for (let index = 0; index < listTasks.length; index++) {
                const element = listTasks[index];
                if (element.isCompleted == true
                    || element.id == "subscribe_telegram_channel"
                    || element.id == "invite_friends"
                    || element.id == "subscribe_telegram_cryptofam") {
                    continue
                }
                await axios.request("https://api.hamsterkombat.io/clicker/check-task", {
                    method: "post",
                    headers,
                    data: {
                        taskId: element.id
                    }
                })
                break
            }

            // tap
            let syncResp = await axios.request("https://api.hamsterkombat.io/clicker/sync", {
                method: "post",
                headers,
            })
            let syncData = syncResp.data
            let syncUser = syncData.clickerUser
            let availableTaps = syncUser.availableTaps
            let earnPerTap = syncUser.earnPerTap
            while (availableTaps > 100) {
                let rdSec = Math.random() * 10 + 10
                let tapsPerSec = (Math.floor(Math.random() * 10) + 35) * earnPerTap
                await sleep(rdSec * 1000)
                let tapsTotal = rdSec * tapsPerSec // 1s: 15~20taps
                const data = {
                    count: Math.floor(tapsTotal),
                    availableTaps: availableTaps,
                    timestamp: Math.floor(Date.now() / 1000),
                }
                syncResp = await axios.request("https://api.hamsterkombat.io/clicker/tap", {
                    method: "post",
                    headers,
                    data: data,
                })
                syncData = syncResp.data
                syncUser = syncData.clickerUser
                availableTaps = syncUser.availableTaps
            }
            // boost
            while (syncUser.maxTaps < 20000) {
                const boostResp = await axios.request("https://api.hamsterkombat.io/clicker/boosts-for-buy", {
                    method: "post",
                    headers
                })
                const boostsForBuy = boostResp.data.boostsForBuy
                const boostMaxTaps = boostsForBuy.find((item) => item.id == "BoostMaxTaps")
                if (syncUser.balanceCoins < boostMaxTaps.price) {
                    break
                }
                const resp = await axios.request("https://api.hamsterkombat.io/clicker/buy-boost", {
                    method: "post",
                    headers,
                    data: {
                        timestamp: Math.floor(Date.now() / 1000),
                        boostId: "BoostMaxTaps",
                    }
                })
                syncUser = resp.data.clickerUser
                break
            }

            while (syncUser.earnPerTap < 20) {
                const boostResp = await axios.request("https://api.hamsterkombat.io/clicker/boosts-for-buy", {
                    method: "post",
                    headers
                })
                const boostsForBuy = boostResp.data.boostsForBuy
                const boostEarnPerTap = boostsForBuy.find((item) => item.id == "BoostEarnPerTap")
                if (syncUser.balanceCoins < boostEarnPerTap.price) {
                    break
                }
                const resp = await axios.request("https://api.hamsterkombat.io/clicker/buy-boost", {
                    method: "post",
                    headers,
                    data: {
                        timestamp: Math.floor(Date.now() / 1000),
                        boostId: "BoostEarnPerTap",
                    }
                })
                syncUser = resp.data.clickerUser
                break
            }

            // upgrade cards
            const upgradeForBuyResp = await axios.request("https://api.hamsterkombat.io/clicker/upgrades-for-buy", {
                method: "post",
                headers,
            })
            const upgradesForBuy = upgradeForBuyResp.data.upgradesForBuy
            for (let index = 0; index < upgradesForBuy.length; index++) {
                const element = upgradesForBuy[index];
                if (element.isAvailable == false || element.isExpired == true) {
                    continue
                }
                if (syncUser.balanceCoins < element.price) {
                    continue
                }
                if (element.level > element.maxLevel) {
                    continue
                }
                try {
                    const resp = await axios.request("https://api.hamsterkombat.io/clicker/buy-upgrade", {
                        method: "post",
                        headers,
                        data: {
                            upgradeId: element.id,
                            timestamp: Date.now(),
                        }
                    })
                    syncUser = resp.data.clickerUser
                } catch (error) {
                    console.log(error.response.data)
                } finally {
                    break
                }
            }

            // update score
            const balance = syncUser.earnPassivePerHour
            await this.sqlconn.query("update hamsterkombat set score=?, sync=1, score_update=? where id=?", [Math.floor(balance), Date().toString(), this.tokenInfo.id])
            console.log(Date(), "game finished", syncUser.id, syncUser.balanceCoins, '/', syncUser.totalCoins)
        } catch (error) {
            if (error.response.status == 407) {
                console.error(Date(), this.proxyInfo, error.response.statusText)
            } else {
                console.error(error)
            }
        }
    }
}

runWorker();